package com.inkyi.assistant.core.todolist.service;

import com.inkyi.assistant.core.system.service.InkDfsService;
import com.inkyi.assistant.core.todolist.entity.InkTodoAttachment;
import com.inkyi.assistant.core.todolist.entity.InkTodoGroup;
import com.inkyi.assistant.core.todolist.entity.InkTodoRecord;
import com.inkyi.assistant.core.todolist.repository.InkTodoAttachmentRepository;
import com.inkyi.assistant.core.todolist.repository.InkTodoGroupRepository;
import com.inkyi.assistant.core.todolist.repository.InkTodoRecordRepository;
import com.inkyi.assistant.core.todolist.repository.InkTodoTaskRepository;
import com.inkyi.assistant.core.utils.JpaUtil;
import com.inkyi.framework.common.utils.EmptyHelper;
import com.inkyi.framework.common.utils.FileHelper;
import com.inkyi.framework.common.utils.IdUtil;
import com.inkyi.framework.dfs.DfsFileMate;
import jakarta.annotation.Resource;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class InkTodoService {

    private final String storageId = "todolist";

    @Resource
    private InkTodoGroupRepository todoGroupRepository;
    @Resource
    private InkTodoRecordRepository todoRecordRepository;
    @Resource
    private InkTodoTaskRepository todoTaskRepository;
    @Resource
    private InkTodoAttachmentRepository todoAttachmentRepository;
    @Resource
    private InkDfsService inkDfsService;
    @PersistenceContext
    private EntityManager entityManager;

    /**
     * 保存附件
     *
     * @param recordId 记录id
     * @param file     文件
     */
    public void saveAttachment(Long recordId, File file) {
        DfsFileMate fileMate = inkDfsService.saveFile(storageId, file);
        InkTodoAttachment attachment = new InkTodoAttachment();
        attachment.setCreateTime(LocalDateTime.now());
        attachment.setUpdateTime(LocalDateTime.now());
        attachment.setRecordId(recordId);
        attachment.setFileName(fileMate.getFileName());
        attachment.setFileSize(FileHelper.formatFileSize(fileMate.getFileSize()));
        attachment.setFileStoreId(fileMate.getFileId());
        attachment.setFileStoreId("DFS");
        todoAttachmentRepository.save(attachment);
    }

    /**
     * 删除附件记录
     *
     * @param recordId 记录id
     */
    public void delAttachmentRecord(Long recordId) {
        InkTodoAttachment attachment = new InkTodoAttachment();
        attachment.setRecordId(recordId);
        List<InkTodoAttachment> attachments = todoAttachmentRepository.findAll(Example.of(attachment));
        if (EmptyHelper.isNotEmpty(attachments)) {
            for (InkTodoAttachment item : attachments) {
                inkDfsService.delFile(storageId, item.getFileStoreId());
                todoAttachmentRepository.deleteById(item.getId());
            }
        }
    }

    /**
     * 下载附件记录
     *
     */
    public String downloadAttachment(Long attachmentId) {
        InkTodoAttachment attachment = todoAttachmentRepository.findById(attachmentId).orElse(null);
        if (attachment == null) {
            return null;
        }
        String fileStoreId = attachment.getFileStoreId();
        String filePath = inkDfsService.findPathByFileId(storageId, fileStoreId);
        return filePath;
    }

    public Page<InkTodoGroup> groupList(String title, Integer pageNum, Integer pageSzie) {
        Specification<InkTodoGroup> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<InkTodoGroup> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (EmptyHelper.isNotEmpty(title)) {
                    List<Predicate> temp = new ArrayList<>();
                    temp.add(criteriaBuilder.like(root.<String>get("title"), "%" + title + "%"));
                    predicates.add(criteriaBuilder.or(temp.toArray(new Predicate[0])));
                }
                return criteriaQuery.where(predicates.toArray(new Predicate[0])).getRestriction();
            }
        };
        return todoGroupRepository.findAll(specification, PageRequest.of(pageNum - 1, pageSzie));
    }

    /**
     * 添加分组
     *
     * @param group
     */
    public void saveGroup(InkTodoGroup record) {
        if (record == null) {
            return;
        }
        if (EmptyHelper.isEmpty(record.getCode())) {
            record.setCode(IdUtil.simpleUUID());
        }
        if (record.getId() != null && todoGroupRepository.existsById(record.getId())) {
            InkTodoGroup dbData = todoGroupRepository.findById(record.getId()).orElse(null);
            JpaUtil.copyNotNullProperties(record, dbData);
            todoGroupRepository.save(dbData);
        } else {
            todoGroupRepository.save(record);
        }
    }

    /**
     * 添加分组
     *
     * @param record
     */
    public void saveGroupByCode(InkTodoGroup record) {
        if (record == null) {
            return;
        }
        record.setId(null);
        String code = record.getCode();
        if (EmptyHelper.isEmpty(code)) {
            return;
        }
        InkTodoGroup query = new InkTodoGroup();
        query.setCode(code);
        InkTodoGroup dbData = todoGroupRepository.findOne(Example.of(query)).orElse(null);
        if (dbData != null) {
            JpaUtil.copyNotNullProperties(record, dbData);
            todoGroupRepository.save(dbData);
            JpaUtil.copyNotNullProperties(dbData, record);
        } else {
            todoGroupRepository.save(record);
        }
    }

    /**
     * 删除分组
     *
     * @param groupId
     * @param delRecord
     */
    public void delGroup(Long groupId, boolean delRecord) {
        todoGroupRepository.deleteById(groupId);
        // 处理Record
        InkTodoRecord queryRecord = new InkTodoRecord();
        queryRecord.setGroupId(groupId);
        List<InkTodoRecord> records = todoRecordRepository.findAll(Example.of(queryRecord));
        if (delRecord) {
            for (InkTodoRecord rec : records) {
                todoRecordRepository.deleteById(rec.getId());
                todoTaskRepository.deleteInkTodoTaskByRecordId(rec.getId());
                todoAttachmentRepository.deleteInkTodoAttachmentByRecordId(rec.getId());
            }
        } else {
            for (InkTodoRecord rec : records) {
                rec.setGroupId(0L);
            }
            todoRecordRepository.saveAll(records);
        }
    }

    public Page<InkTodoRecord> recordList(Map<String, Object> params, Integer pageNum, Integer pageSzie) {
        Long groupId = (Long) params.get("groupId");
        String groupType = (String) params.get("groupType");
        Specification<InkTodoRecord> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<InkTodoRecord> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (Objects.equals("jintian", groupType)) {
                    predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("todoTime"), LocalDate.now()));
                    predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("todoTime"), LocalDate.now()));
                } else if (Objects.equals("zhongyao", groupType)) {
                    predicates.add(criteriaBuilder.equal(root.<Integer>get("priority"), 1));
                } else if (Objects.equals("yiwancheng", groupType)) {
                    predicates.add(criteriaBuilder.equal(root.<Boolean>get("isFinish"), true));
                } else if (Objects.equals("quanbu", groupType)) {
                } else if (Objects.equals("group", groupType)) {
                    if (groupId != null) {
                        predicates.add(criteriaBuilder.equal(root.<Long>get("groupId"), groupId));
                    }
                }
                return criteriaQuery.where(predicates.toArray(new Predicate[0])).getRestriction();
            }
        };
        return todoRecordRepository.findAll(specification, PageRequest.of(pageNum - 1, pageSzie));
    }

    public void recordSave(InkTodoRecord record) {
        if (record == null) {
            return;
        }
        if (record.getId() != null && todoRecordRepository.existsById(record.getId())) {
            InkTodoRecord dbData = todoRecordRepository.findById(record.getId()).orElse(null);
            JpaUtil.copyNotNullProperties(record, dbData);
            todoRecordRepository.save(dbData);
        } else {
            todoRecordRepository.save(record);
        }
    }

    public void recordDel(Long id) {
        todoRecordRepository.deleteById(id);
    }

    public InkTodoRecord recordOne(Long id) {
        return todoRecordRepository.findById(id).orElse(null);
    }

    public InkTodoGroup groupOne(Long id) {
        return todoGroupRepository.findById(id).orElse(null);
    }
}
